/**
 * 验证数据是否正确
 * Created by clakeboy on 16/11/5.
 */
(function(){
    if (typeof window.ZSY == 'undefined') window.ZSY = {};

    ZSY.getValid = function() {
        return new ZSY.valid();
    };

    ZSY.valid = (function(){
        var _reg = {
            "match":/^(.+?)(\d+)-(\d+)$/,
            "*":/[\w\W]+/,
            "*6-16":/^[\w\W]{6,16}$/,
            "n":/^\d+$/,
            "f":/^\d+(\.?)\d{0,3}$/,
            "n6-16":/^\d{6,16}$/,
            "s":/^[\u4E00-\u9FA5\uf900-\ufa2d\w\.\s\d]+$/,
            "s6-18":/^[\u4E00-\u9FA5\uf900-\ufa2d\w\.\s\d]{6,18}$/,
            "p":/^[0-9]{6}$/,
            "m":/^13[0-9]{9}$|14[0-9]{9}|15[0-9]{9}$|18[0-9]{9}|17[0-9]{9}$/,
            "e":/^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
            "url":/^(\w+:\/\/)?\w+(\.\w+)+.*$/,
            "d":/^\d{4}-\d{1,2}-\d{1,2}$/,
            "dt":/^\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:?\d{0,2}$/
        };

        function _getBasePath() {
            var reg = /zsy_valid.js/i;
            var _url = '';
            $('script').each(function(){
                if (reg.test(this.src)) {
                    _url = this.src.substr(0,this.src.toLocaleLowerCase().lastIndexOf('zsy_valid.js'));
                    return;
                }
            });
            return _url;
        }

        function _initWindow() {
            var _basePath = _getBasePath();
            $('<link/>').attr({'rel':'stylesheet','type':'text/css','href':_basePath+'valid.css'})
                .appendTo('head');
        }
        _initWindow();
        return function() {
            /**
             * private property
             */
            var _list = {};
            var _options = {};
            var _success_evt = function(check){};
            var _remote = {};
            var _remoteFlag = {};
            var _submit = false;
            /**
             * private function
             */
            function _explainDataType(data) {
                if (!data) return null;
                var reg = _reg[data] || null;
                if (reg) {
                    return reg;
                } else {
                    var match = data.match(_reg.match);
                    if (match) {
                        if (match[1] == 'n') {
                            reg = new RegExp("^\\d{"+match[2]+","+match[3]+"}$");
                        } else if (match[1] == 's') {
                            reg = new RegExp('^[\\u4E00-\\u9FA5\\uf900-\\ufa2d\\w\\.\\s\\d]{'+match[2]+','+match[3]+'}$');
                        } else if (match[1] == '*') {
                            reg = new RegExp("^[\\w\\W]{"+match[2]+","+match[3]+"}$");
                        }
                    }
                    return reg;
                }
            }

            function _mutiCheck(val) {
                if (!val) {
                    return null;
                }
                var arr = val.split('-');
                return {'min':parseInt(arr[0]),'max':parseInt(arr[1])};
            }

            function _init(selector) {
                //init option
                if (typeof arguments[2] == 'object') {
                    _options = arguments[2];
                }
                //init success callback function
                if (typeof arguments[1] == 'function') {
                    _success_evt = arguments[1];
                }
                $(selector+' input').each(function(){
                    var obj = $(this);
                    _initValidList(obj);
                });
                $(selector+' select').each(function(){
                    var obj = $(this);
                    obj.attr('vitype','select');
                    _initValidList(obj);
                });
                $(selector+' textarea').each(function(){
                    var obj = $(this);
                    obj.attr('vitype','textarea');
                    _initValidList(obj);
                });
            };

            function _initValidList(obj) {
                if (obj.attr('datatype') || obj.attr('recheck') || obj.attr('nullmsg') || obj.attr('tipmsg')) {
                    var name = obj.attr('id');
                    _list[name] = {
                        'name':obj.attr('id'),
                        'isNull':obj.attr('isnull')?true:false,
                        'errorMsg':obj.attr('errormsg'),
                        'nullMsg':obj.attr('nullmsg'),
                        'tipMsg':obj.attr('tipmsg'),
                        'valid':obj.attr('valid') === "true"?true:false,
                        'dataType':_explainDataType(obj.attr('datatype')),
                        'reCheck':obj.attr('recheck'),
                        'ele':obj.get(0),
                        'tip':_initTip(),
                        'tipPosition':obj.attr('tippos')||'bottom',
                        'tipType':obj.attr('tipfix') == 'f' ? 'fixed' : 'absolute',
                        'type':obj.attr('type') || obj.attr('vitype'),
                        'tipCss':obj.attr('tipcss'),
                        'def':obj.attr('def'),
                        'remote':obj.attr('remote'),
                        'remoteVar':obj.attr('remotevar'),
                        'url':obj.attr('remoteurl'),
                        'pw':obj.attr('pw'),
                        'remoteValid':obj.attr('remotevalid')?obj.attr('remotevalid'):null,
                        'muti':_mutiCheck(obj.attr('muti'))
                    };

                    if (_list[name].remote) {
                        _remoteFlag[name] = false;
                    }

                    if (_list[name].type == 'checkbox' ) {
                        obj.change(function(){
                            _check($(this).attr('id'));
                        });
                    } else {
                        obj.focus(function(){
                            if (_list[name].def && _list[name].def == $(this).val()) {
                                obj.removeClass('zsy_valid_def');

                                $(this).val('');
                            }
                            _setStatus($(this).attr('id'),true,true);
                        })
                            .blur(function(){
                                if (_list[name].def && $(this).val().trim() == '') {
                                    obj.addClass('zsy_valid_def');

                                    $(this).val(_list[name].def);
                                }
                                _check($(this).attr('id'));
                                _submit = false;
                            })
                            .change(function(){
                                _list[$(this).attr('id')].remoteValid = null;
                            });
                    }

                    if (_list[name].def) {
                        obj.addClass('zsy_valid_def');
                        obj.val(_list[name].def);
                    }
                }
            }

            function _initTip() {
                var tip = $('<div/>');
                tip.addClass('zsy_valid_tip');
                tip.appendTo('body');
                return tip.get();
            }

            function _validata(name,flag) {
                if (flag !== null) {
                    _list[name].valid = flag;
                    _list[name].ele.scrollIntoView();
                } else {
                    var val = $(_list[name].ele).val();

                    if (_list[name].def) {
                        val = val == _list[name].def ? "":val;
                    }

                    if (_list[name].isNull && val.trim() == '') {
                        return _list[name].valid = true;
                    }

                    if (_list[name].type == 'checkbox') {
                        _list[name].valid = $(_list[name].ele).attr('checked') == undefined ? false:true;
                    } else if (_list[name].reCheck) {
                        if (val !== $('#'+_list[name].reCheck).val()) {
                            _list[name].valid = false;
                        } else if (_list[name].dataType) {
                            _list[name].valid = _list[name].dataType.test(val);
                        } else {
                            _list[name].valid = true;
                        }
                    } else {
                        if (_list[name].dataType) {
                            _list[name].valid = _list[name].dataType.test(val);
                        } else {
                            _list[name].valid = true;
                        }
                    }
                }

                return _list[name].valid;
            }

            function _check() {
                var name = arguments[0] || null;
                var flag = typeof arguments[1] == 'undefined'?null:arguments[1];
                var msg = typeof arguments[1] == 'undefined'?null:arguments[2];

                var return_flag = true;
                if (name) {
                    if (msg) {
                        _list[name].errorMsg = msg;
                    }
                    return_flag = _validata(name,flag);
                    if (return_flag && _list[name].remote) {
                        if (_list[name].remoteValid === null) {
                            return_flag = false;
                            _startRemoteValid(_list[name]);
                        } else {
                            return_flag = return_flag && _list[name].remoteValid;
                            _setStatus(name,return_flag);
                        }
                    } else {
                        _setStatus(name,return_flag);
                    }
                } else {
                    for (var key in _list) {
                        return_flag = _check(key,flag);
                        if (!return_flag) {
                            _scroll(_list[key].ele);
//							_list[key].ele.focus();
                            break;
                        }
                    }
                    _success_evt(return_flag);
                }
                return return_flag;
            };

            function _setStatus(name,valid) {
                var status = typeof arguments[2] === "undefined" ? false:true;
                var obj = _list[name];
                if (status === true) {
                    if (obj.tipMsg) {
                        _showTip(name,obj.tipMsg,'focus',obj.tipPosition);
                    } else {
                        _closeTip(name);
                    }
                } else if (valid) {
                    _closeTip(name);
                } else {
                    var val = $(obj.ele).val();
                    if (obj.def) {
                        var val = val == obj.def ? "":val;
                    }
                    var msg = _reg['*'].test(val)?obj.errorMsg:obj.nullMsg;
                    _showTip(name,msg,'error',obj.tipPosition);
                }
            };

            function _showTip(name,msg,type,pos) {
                var obj = _list[name];
                if (obj.type == "hidden") {
                    alert(msg);
                    return;
                }
                var offset=$(obj.ele).offset(),
                    out_height=$(obj.ele).outerHeight(),
                    in_height=$(obj.ele).innerHeight(),
                    out_width=$(obj.ele).outerWidth(),
                    in_width=$(obj.ele).innerWidth(),
                    top,left;
                $(obj.ele).addClass('zsy_valid_'+type);
                $(obj.tip).addClass('zsy_valid_tip_'+type);
                switch(pos) {
                    case "top":
                        top = parseInt(offset.top) - out_height;
                        left = parseInt(offset.left);
                        break;
                    case "bottom":
                        top = parseInt(offset.top) + out_height;
                        left = parseInt(offset.left)+1;
                        break;
                    case "left":
                        top = parseInt(offset.top);
                        left = parseInt(offset.left) - out_width;
                        $(obj.tip).height(in_height).css({'lineHeight':in_height+'px'});
                        break;
                    case "right":
                        top = parseInt(offset.top);
                        left = parseInt(offset.left) + out_width;
                        $(obj.tip).height(in_height).css({'lineHeight':in_height+'px'});
                        break;
                }

                var con = msg.split('|');
                msg = con.length>1?con[1]:con[0];

                $(obj.ele).removeClass('zsy_valid_error zsy_valid_focus').addClass('zsy_valid_'+type);

                $(obj.tip).removeClass('zsy_valid_tip_focus zsy_valid_tip_error zsy_valid_tip_height1')
                    .addClass('zsy_valid_tip_'+type)
                    .css({'top':top,'left':left,'position':obj.tipType})
                    .text(msg);
                if (in_width > 20) {
                    $(obj.tip).width(in_width-10);
                }
                $(obj.tip).show(500);

                if (con.length > 1) {
                    $(obj.tip).addClass('zsy_valid_tip_'+con[0]);
                }
            }

            function _closeTip(name) {
                var obj = _list[name];
                $(obj.ele).removeClass('zsy_valid_error zsy_valid_focus');
                $(obj.tip).removeClass('zsy_valid_tip_focus zsy_valid_tip_error').hide();
            }

            function _closeAllTip() {
                for (var key in _list) {
                    $(_list[key].tip).removeClass('zsy_valid_tip_focus zsy_valid_tip_error').hide();
                }
            }

            function _close() {
                for (var key in _list) {
                    _setStatus(key,true);
                }
            };

            function _scroll(obj) {
                var offset = $(obj).offset();
                var scrollTop = $(document).scrollTop();
                if (scrollTop > offset['top']) {
                    var top = offset['top'] - ($(window).height())/2;
                    $(document).scrollTop(top > 0 ? top : 0);
                }
            }

            //remoto check function
            function _startRemoteValid(item) {
                var serv = item.url.split('|')[0];
                var func = item.url.split('|')[1];
                if (!_remote[item.name]) {
                    _remote[item.name] = new PHPRPC_Client(serv,[func]);
                }
                var rpc = _remote[item.name];
                _showTip(item.name,'验证中...','focus',item.tipPosition);
                rpc.invoke(func,$(item.ele).val(),item.remoteVar,function(result){
                    var valid = JSON.parse(result);
                    if (valid.status === true) {
                        item.remoteValid = true;
                        _remoteFlag[item.name] = true;
                        _closeTip(item.name);
                        _checkRemote();
                    } else {
                        item.remoteValid = false;
                        _showTip(item.name,valid.msg,'error',item.tipPosition);
                    }
                });
            }

            function _checkRemote() {
                var flag = true;
                for (var k in _remoteFlag) {
                    if (_remoteFlag[k] === false) {
                        flag = false;
                    }
                }
                if (flag && _submit) {
                    _check();
                }
            }

            function _reset() {
                _submit = false;
            }

            function _submitClick() {
                _submit = true;
                _check(arguments[0],arguments[1],arguments[2]);
            }
            /**
             * public property
             */
            this.list = _list;
            /**
             * public function
             */
            this.check = _check;
            this.init = _init;
            this.close = _close;
            this.closeAll = _closeAllTip;
            this.reset = _reset;
        };
    })();
})();